<template>
  <div>
    <basic-dialog :visible="visible" min-width="626px"
                  :title="title">
      <q-form @submit="onSubmit"
              greedy
              @reset="reset"
              ref="myForm"
              class="dialog-content block">
        <div style="padding: 20px 20px 0 20px">
          <div class="title">设备信息</div>
          <div class="flex">
            <q-select v-model="form.assetNumber"
                      :options="numOption"
                      dense
                      options-dense
                      emit-value
                      map-options
                      outlined
                      :disable="isEdit"
                      class="select-width margin-r-20"
                      :rules="[ val => val !== '' || ' 请选择设备编号']">
              <template v-slot:option="scope">
                <q-item
                  v-bind="scope.itemProps"
                  v-on="scope.itemEvents"
                >
                  <q-item-section>
                    <q-item-label v-html="scope.opt.value" ></q-item-label>
                  </q-item-section>
                  <q-item-section side>
                    <q-item-label v-html="scope.opt.name" />
                  </q-item-section>
                </q-item>
              </template>
              <template v-slot:no-option>
                <div class="no-option" />
              </template>
              <template v-slot:before>
                <label class="text-right name label-width">
                  <span class="text-red">*</span><span>设备编号:</span>
                </label>
              </template>
            </q-select>
            <label class="text-right name label-width">
              <span class="text-red">*</span><span>设备类型:</span>
            </label>
            <label class="name label-width margin-l-10" style="width: 178px;">{{ form.deviceTypeIot }}</label>
          </div>
          <div class="flex">
            <q-select v-model="form.deviceFactoryIot"
                      :options="factoryOption"
                      dense
                      options-dense
                      emit-value
                      map-options
                      outlined
                      class="select-width margin-r-20"
                      :rules="[ val => val !== '' || ' 请选择设备厂家']">
              <template v-slot:no-option>
                <div class="no-option" />
              </template>
              <template v-slot:before>
                <label class="text-right name label-width">
                  <span class="text-red">*</span><span>设备厂家:</span>
                </label>
              </template>
            </q-select>
            <q-select v-model="form.deviceSerialIot"
                      :options="modelOption"
                      dense
                      options-dense
                      emit-value
                      map-options
                      outlined
                      class="select-width"
                      :rules="[ val => val !== '' || ' 请选择设备型号']">
              <template v-slot:no-option>
                <div class="no-option" />
              </template>
              <template v-slot:before>
                <label class="text-right name label-width">
                  <span class="text-red">*</span><span>设备型号:</span>
                </label>
              </template>
            </q-select>
          </div>
          <div class="flex">
            <q-select v-model="form.deviceProtocolIot"
                      :options="protocolOption"
                      dense
                      options-dense
                      emit-value
                      map-options
                      outlined
                      class="select-width margin-r-20"
                      :rules="[ val => val !== '' || ' 请选择通讯协议']">
              <template v-slot:no-option>
                <div class="no-option" />
              </template>
              <template v-slot:before>
                <label class="text-right name label-width">
                  <span class="text-red">*</span><span>通讯协议:</span>
                </label>
              </template>
            </q-select>
            <q-select v-model="form.communicationTypeIot"
                      :options="methodsOption"
                      dense
                      options-dense
                      emit-value
                      map-options
                      outlined
                      class="select-width"
                      :rules="[ val => val !== '' || ' 请选择通讯方式']">
              <template v-slot:no-option>
                <div class="no-option" />
              </template>
              <template v-slot:before>
                <label class="text-right name label-width">
                  <span class="text-red">*</span><span>通讯方式:</span>
                </label>
              </template>
            </q-select>
          </div>

        </div>
        <q-separator />
        <div class="dialog-footer text-center margin-t-10">
          <q-btn outline
                 label="取消"
                 color="primary"
                 :disable="submitting"
                 class="q-mr-md"
                 type="reset" />
          <q-btn unelevated
                 label="下一步"
                 v-throttle
                 :loading="submitting"
                 color="primary"
                 type="submit" />
        </div>
      </q-form>
    </basic-dialog>
  </div>
</template>

<script>
import BasicDialogMixin from 'src/components/common/basic-dialog/src/basic-dialog-mixin'
import {
  getBoxProducts,
  getDeviceCascade
} from '../../../../boot/miot/list'
import _ from 'lodash'
// eslint-disable-next-line no-unused-vars
import { checkOnlineStatus, deviceBindBoxSub, driverUpdate, driverVersionCompare } from '../../../../boot/miot/details'
import { Dialog } from 'quasar'
import { mapGetters } from 'vuex'

export default {
  name: 'add-edit-binding-equipment',
  mixins: [BasicDialogMixin],
  computed: {
    formTemp () {
      return _.cloneDeep(this.form)
    },
    title () {
      if (this.formData) {
        return '编辑绑定设备'
      }
      return '新增绑定设备'
    },
    isEdit () {
      return !!this.formData
    },
    ...mapGetters(['userInfo', 'client'])
  },
  props: {
    deviceNum: {
      type: String,
      default: null
    },
    formData: {
      type: Object,
      default: null
    },
    numOption: {
      type: Array,
      default: () => []
    },
    boxId: {
      type: String,
      default: ''
    },
    productName: {
      type: String,
      default: ''
    },
    controllerType: {
      type: String,
      default: ''
    }
  },
  watch: {
    visible (val) {
      if (val && this.controllerType) {
        this.form.deviceTypeIot = this.controllerTypeObj[this.controllerType]
      }
    },
    productName () {
      this.getDeviceCascade()
    },
    controllerType: {
      immediate: true,
      handler (val) {
        this.form.deviceTypeIot = this.controllerTypeObj[val]
      }
    },
    formData: {
      deep: true,
      immediate: true,
      handler: function (val) {
        if (val) {
          this.form.assetNumber = val.assetNumber
          this.form.deviceTypeIot = val.deviceTypeIot
          this.form.deviceFactoryIot = val.deviceFactoryIot
          this.form.deviceSerialIot = val.deviceSerialIot
          this.form.deviceProtocolIot = val.deviceProtocolIot
          this.form.communicationTypeIot = val.communicationTypeIot
        } else {
          Object.assign(this.form, this.$options.data().form)
        }
      }
    },
    formTemp: {
      deep: true,
      handler: function (val, oldVal) {
        // 如果旧值有assetNumber才证明初始化过了，否则执行初始化
        if (val && oldVal && (!this.isEdit || oldVal.assetNumber)) {
          // 设备类型改变
          if (val.deviceTypeIot !== oldVal.deviceTypeIot) {
            this.modelOption = []
            this.protocolOption = []
            this.methodsOption = []
            this.factoryOption = []
            this.form.deviceFactoryIot = ''
            this.form.deviceSerialIot = ''
            this.form.deviceProtocolIot = ''
            this.form.communicationTypeIot = ''
            const typeParentId = 0
            const data = this.deviceMap.get(val.deviceTypeIot + typeParentId)
            this.dataToOptions(data, this.factoryOption)
          }

          // 设备厂家改变
          if (val.deviceFactoryIot !== oldVal.deviceFactoryIot) {
            this.protocolOption = []
            this.methodsOption = []
            this.modelOption = []
            this.form.deviceSerialIot = ''
            this.form.deviceProtocolIot = ''
            this.form.communicationTypeIot = ''
            const factoryParentId = this.factoryOption.find(item => item.value === val.deviceFactoryIot) ? this.factoryOption.find(item => item.value === val.deviceFactoryIot).parentId : ''
            const data = this.deviceMap.get(val.deviceFactoryIot + factoryParentId)
            this.dataToOptions(data, this.modelOption)
          }

          // 设备型号改变
          if (val.deviceSerialIot !== oldVal.deviceSerialIot) {
            this.protocolOption = []
            this.methodsOption = []
            this.form.deviceProtocolIot = ''
            this.form.communicationTypeIot = ''
            const serialParentId = this.modelOption.find(item => item.value === val.deviceSerialIot) ? this.modelOption.find(item => item.value === val.deviceSerialIot).parentId : ''
            const data = this.deviceMap.get(val.deviceSerialIot + serialParentId)
            this.dataToOptions(data, this.protocolOption)
          }

          // 通讯方式协议
          if (val.deviceProtocolIot !== oldVal.deviceProtocolIot) {
            this.methodsOption = []
            this.form.communicationTypeIot = ''
            const protocolParentId = this.protocolOption.find(item => item.value === val.deviceProtocolIot) ? this.protocolOption.find(item => item.value === val.deviceProtocolIot).parentId : ''
            const data = this.deviceMap.get(val.deviceProtocolIot + protocolParentId)
            this.dataToOptionsProtocolIot(data, this.methodsOption)
          }
        } else {
          // 如果是初始化的时候
          const typeParentId = 0
          this.dataToOptions(this.deviceMap.get(val.deviceTypeIot + typeParentId), this.factoryOption)
          const factoryParentId = this.factoryOption.find(item => item.value === val.deviceFactoryIot) ? this.factoryOption.find(item => item.value === val.deviceFactoryIot).parentId : ''
          this.dataToOptions(this.deviceMap.get(val.deviceFactoryIot + factoryParentId), this.modelOption)
          const serialParentId = this.modelOption.find(item => item.value === val.deviceSerialIot) ? this.modelOption.find(item => item.value === val.deviceSerialIot).parentId : ''
          this.dataToOptions(this.deviceMap.get(val.deviceSerialIot + serialParentId), this.protocolOption)
          const protocolParentId = this.protocolOption.find(item => item.value === val.deviceProtocolIot) ? this.protocolOption.find(item => item.value === val.deviceProtocolIot).parentId : ''
          this.dataToOptionsProtocolIot(this.deviceMap.get(val.deviceProtocolIot + protocolParentId), this.methodsOption)
        }
      }
    }
  },
  data () {
    return {
      submitting: false,
      form: {
        assetNumber: '',
        deviceTypeIot: '',
        deviceFactoryIot: '',
        deviceSerialIot: '',
        deviceProtocolIot: '',
        communicationTypeIot: ''
      },
      typeOption: [],
      factoryOption: [],
      modelOption: [],
      protocolOption: [],
      methodsOption: [],
      deviceMap: new Map(),
      products: [],
      timer: null,
      checkTimes: 0,
      subscribe: null,
      controllerTypeObj: {
        '1': 'CNC'
      }
    }
  },
  created () {
    this.getBoxProducts()
  },
  methods: {
    // 提交表单
    onSubmit () {
      this.submitBindingEquipment()
    },

    async getBoxProducts () {
      const { data } = await getBoxProducts()
      if (data && data.products) {
        this.products = data.products
      } else {
        this.products = []
      }
    },

    async getDeviceCascade () {
      try {
        const { data } = await getDeviceCascade(this.productName)
        if (data && data.children && data.children.length > 0) {
          this.deviceToMap(data.children)
          console.log(this.deviceMap)
          this.dataToOptions(data.children, this.typeOption)
        } else {
          this.typeOption = []
        }
      } catch (e) {
        this.typeOption = []
      }
    },

    deviceToMap (data) {
      if (data && data.length > 0) {
        data.forEach(item => {
          this.deviceMap.set(item.name + item.parentId, item.children)
          if (item.children && item.children.length > 0) {
            this.deviceToMap(item.children)
          }
        })
      }
    },

    dataToOptions (data, option) {
      if (data && data.length > 0) {
        data.forEach(item => {
          option.push({
            label: item.name,
            value: item.name,
            parentId: item.parentId
          })
        })
      }
    },
    dataToOptionsProtocolIot (data, option) {
      if (data && data.length > 0) {
        data.forEach(item => {
          option.push({
            label: item.name === 'LAN' || item.name === 'lan' ? item.name + '/PCMCIA' : item.name,
            value: item.name,
            parentId: item.parentId
          })
        })
      }
    },
    /**
     * 提交绑定设备
     * @returns {Promise<void>}
     */
    async submitBindingEquipment () {
      this.submitting = true
      const productName = `${this.form.deviceTypeIot}_${this.form.deviceFactoryIot}_${this.form.deviceSerialIot}_${this.form.deviceProtocolIot}_${this.form.communicationTypeIot}`
      // 如果是编辑的话，否则是新增
      if (this.isEdit) {
        const softWareOld = `${this.formData.deviceTypeIot}_${this.formData.deviceFactoryIot}_${this.formData.deviceSerialIot}_${this.formData.deviceProtocolIot}_${this.formData.communicationTypeIot}`
        const params0 = {
          boxId: this.boxId,
          deviceId: this.deviceNum,
          productName: this.productName,
          softWare: productName,
          type: 'Driver',
          softWareOld: productName
        }

        const params = {
          boxId: this.boxId,
          deviceId: this.deviceNum,
          productName: this.productName,
          softWare: productName,
          softWareOld: softWareOld
        }
        try {
          const data = await driverVersionCompare(params0)
          if (data.data && data.data.compareRes === 1) {
            await driverUpdate(params)
          } else {
            checkOnlineStatus(this.deviceNum)
          }
          // 检测盒子子设备是否在线
          try {
            await this.checkOnline(this.deviceNum)
          } catch (e) {
            this.$emit('deviceOffline', this.form)
            return
          }
          this.$emit('successSubmit', this.form)
        } catch (e) {
        }
      } else {
        try {
          const data = []
          const index = this.products.findIndex(item => item.name === 'CNC_Model')
          data.push({
            ...this.form,
            productName: this.productName,
            productId: index > -1 ? this.products[index].product_id : '',
            boxNum: this.boxId
          })
          // 绑定设备
          const rs = await deviceBindBoxSub(data)
          if (rs.success) {
            // 检测盒子子设备是否在线
            try {
              await this.checkOnline(this.form.assetNumber)
              this.submitting = false
            } catch (e) {
              this.$emit('deviceOffline', this.form)
              this.submitting = false
              return
            }
            this.submitting = false
            this.$emit('successSubmit', this.form)
          } else {
            this.submitting = false
            if (rs.message) {
              this.$message.error(rs.message)
            }
          }
        } catch (e) {
          this.submitting = false
        }
      }
      this.submitting = false
    },

    /**
     * 检查盒子是否在线
     */
    checkOnline (deviceNum) {
      const id = this.userInfo.tenant_id + '_' + deviceNum
      return new Promise((resolve, reject) => {
        if (this.client && this.client.connected) {
          this.subscribe = this.client.subscribe(
            `/topic/device/bind/box/${id}`,
            (message) => {
              try {
                this.subscribe.unsubscribe()
                const ret = JSON.parse(message.body)
                if (ret && ret.data && ret.data.status === 'ONLINE') {
                  resolve()
                } else {
                  Dialog.create({
                    title: `<p class="dialog-notice-title">
                <i class="iconfont icontubiao-28" ></i>设备未在线，请检查设备网络</p>`,
                    html: true,
                    ok: {
                      unelevated: true,
                      label: '确认'
                    }
                  })
                  reject()
                }
              } catch (e) {
                console.log('解析socket在线错误' + e)
              }
            }
          )
        } else {
          Dialog.create({
            title: `<p class="dialog-notice-title">
                <i class="iconfont icontubiao-28" ></i>websocket断开连接啦~请稍后重试</p>`,
            html: true,
            ok: {
              unelevated: true,
              label: '确认'
            }
          })
          reject()
        }
      })
    },

    // 清空表单
    reset () {
      this.$emit('close')
      this.submitting = false
      if (this.subscribe) this.subscribe.unsubscribe()
      Object.assign(this.form, this.$options.data().form)
    }
  }
}
</script>

<style scoped lang="stylus">
.select-width
  width 266px
.title
  font-weight 500
  font-size 16px
  color $primary
  margin-bottom 20px
</style>
